#include "../include/ThreadTimerSvc.h"
#include "../include/Debug.h"

#include <map>
#include <signal.h>

ThreadTimerSvc thread_timer_svc;
class HeartBeat;

// not lock protect
std::map<int, HeartBeat*> heartbeat_list;
class HeartBeat : public EventHandler
{
public:
    HeartBeat ()
    : terminate_ (0)
    {}
    ~HeartBeat ()
    {
	NDK_INF ("HeartBeat destroy itself\n");
    }
    int handle_timeout (const void *arg, const TimeValue &curr_time)
    {
	NDK_INF ("thread [%lu] generate an heart beat[arg = %d]," 
		"current time %d.%d, heartbeat list size = %d\n",
		Thread::self (),
		*(reinterpret_cast<const int *>(arg)),
		curr_time.sec (), curr_time.usec () / 1000,
		heartbeat_list.size ());
	return this->terminate_;
    }
    int handle_close (const void *arg, ReactorMask mask)
    {
	NDK_INF ("handle close [arg = %d]\n", *(reinterpret_cast<const int *>(arg)));
	heartbeat_list.erase (*(reinterpret_cast<const int *>(arg)));
	void *a = const_cast<void *>(arg);
	delete reinterpret_cast<int *>(a);
	delete this;
	return 0;
    }
    void terminate ()
    {
	this->terminate_ = -1;
    }
protected:
    int terminate_;
};
void create_heart_beat (int count)
{
    for (int i = 0; i < count; ++i)
    {
	int *timer_id = new int;
	HeartBeat *heart_beat = new HeartBeat;
	heart_beat->terminate ();
	*timer_id = thread_timer_svc.schedule_timer (heart_beat,
		timer_id,
		TimeValue (2, 0),
		TimeValue::zero);
	heartbeat_list.insert (std::make_pair (*timer_id, heart_beat));
    }
}
void create_continuate_beart_beat (int count)
{
    for (int i = 0; i < count; ++i)
    {
	int *timer_id = new int;
	HeartBeat *heart_beat = new HeartBeat;
	*timer_id = thread_timer_svc.schedule_timer (heart_beat,
		timer_id,
		TimeValue (2, 0),
		TimeValue (2, 0));
	heartbeat_list.insert (std::make_pair (*timer_id, heart_beat));
    }
}
void signal_handler (int sig)
{
    switch (sig)
    {
	case SIGINT:
	    NDK_INF ("thread %lu signal INT\n", Thread::self ());
	    thread_timer_svc.deactivate();
	    break;
	case SIGUSR1:
	    NDK_INF ("thread %lu signal USR1\n", Thread::self ());
#if 1
	    {
		create_heart_beat (100);
	    }
#else
	    {
		for (int i = 0; i < 100; ++i)
		{
		    HeartBeat *heart_beat = new HeartBeat;
		    int *timer_id = new int;
		    *timer_id = thread_timer_svc.schedule_timer (heart_beat,
			    timer_id,
			    TimeValue (i, 0),
			    TimeValue::zero);
		    NDK_INF ("registe an once timer id = %d\n", *timer_id);
		}

	    }
#endif
	    break;
	case SIGUSR2:
	    NDK_INF ("thread %lu signal USR2\n", Thread::self ());
#if 1
	    {
		create_continuate_beart_beat (100);
	    }
#else
	    {
		for (int i = 0; i < 100; ++i)
		{
		    HeartBeat *heart_beat = new HeartBeat;
		    int timer_id = thread_timer_svc.schedule_timer (heart_beat,
			    new int(i),
			    TimeValue::zero,
			    TimeValue (i, 0));
		    NDK_INF ("registe an interval timer id = %d\n", timer_id);
		}

	    }
#endif
	    break;
	case SIGHUP:
	    NDK_INF ("thread %lu signal HUP\n", Thread::self ());
#if 1
	    {
		std::map<int, HeartBeat*>::iterator pos;
		int i = 0;
		for (i = 0, pos = heartbeat_list.begin (); 
			i < 120 && pos != heartbeat_list.end (); 
			++i, ++pos)
		{
		    pos->second->terminate ();
		}
	    }
#else 
	    {
		for (int i = 1; i < 120; ++i)
		{
		    thread_timer_svc.cancel_timer (i);
		}
	    }
#endif
	    break;
	case SIGPIPE:
	    {
		std::map<int, HeartBeat*>::iterator pos;
		for (pos = heartbeat_list.begin ();
			pos != heartbeat_list.end ();
			++pos)
		{
		    thread_timer_svc.reset_timer_interval (pos->first,
			TimeValue (4, 0));
		}
	    }
    }
}
int main ()
{
    signal (SIGINT, signal_handler);
    signal (SIGUSR1, signal_handler);
    signal (SIGUSR2, signal_handler);
    signal (SIGHUP, signal_handler);
    signal (SIGPIPE, signal_handler);

    create_continuate_beart_beat (1);

    ThreadManager::instance ()->wait ();
}
